package com.navinfo.truckload;

import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVPrinter;
import org.apache.commons.csv.CSVRecord;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.Reader;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Iterator;
import java.util.List;

/**
 * @author machi
 * @create 2018/12/27
 */
public class CsvUtil {

    /**
     * 写CSV文件
     *
     * @param csvFile
     * @param fileHeader
     * @param values
     * @param charset
     * @param append
     * @throws IOException
     */
    public static void write(final String csvFile, final String[] fileHeader, final Iterable<?> values, final String charset, boolean append)
            throws IOException {
        if (append) {
            try (BufferedWriter writer = Files.newBufferedWriter(Paths.get(csvFile), Charset.forName(charset),
                    StandardOpenOption.APPEND);
                 CSVPrinter csvPrinter = new CSVPrinter(writer, CSVFormat.DEFAULT.withAutoFlush(true))) {
                csvPrinter.printRecords(values);
            } catch (IOException e) {
                e.printStackTrace();
                throw e;
            }
        } else {
            try (BufferedWriter writer = Files.newBufferedWriter(Paths.get(csvFile), Charset.forName(charset));
                 CSVPrinter csvPrinter = new CSVPrinter(writer,
                         CSVFormat.DEFAULT.withHeader(fileHeader).withAutoFlush(true))) {
                csvPrinter.printRecords(values);
            } catch (IOException e) {
                e.printStackTrace();
                throw e;
            }
        }
    }

    /**
     * 写CSV文件
     *
     * @param csvFile    csv文件名称
     * @param fileHeader 文件头
     * @param values     内容
     */
    public static void write(final String csvFile, final String[] fileHeader, final Iterable<?> values, final String charset)
            throws IOException {
        write(csvFile, fileHeader, values, charset, false);
    }

    /**
     * 写CSV文件
     *
     * @param csvFile    csv文件名称
     * @param fileHeader 文件头
     * @param values     内容
     */
    public static void write(final String csvFile, final String[] fileHeader, Iterable<?> values, boolean append)
            throws IOException {
        write(csvFile, fileHeader, values, "gbk", append);
    }

    /**
     * 写CSV文件
     *
     * @param csvFile    csv文件名称
     * @param fileHeader 文件头
     * @param values     内容
     */
    public static void write(final String csvFile, final String[] fileHeader, Iterable<?> values)
            throws IOException {
        write(csvFile, fileHeader, values, "gbk");
    }

    /**
     * 获得CSVPrinter，用于大数据量写入时
     *
     * @param csvFile
     * @param fileHeader
     * @param charset
     * @param append
     * @return
     * @throws IOException
     */
    public static CSVPrinter csvPrinter(final String csvFile, final String[] fileHeader, final String charset, boolean append)
            throws IOException {
        if (append) {
            try (BufferedWriter writer = Files.newBufferedWriter(Paths.get(csvFile), Charset.forName(charset),
                    StandardOpenOption.APPEND);
                 CSVPrinter csvPrinter = new CSVPrinter(writer, CSVFormat.DEFAULT.withAutoFlush(true))) {
                return csvPrinter;
            } catch (IOException e) {
                e.printStackTrace();
                throw e;
            }
        } else {
            try (BufferedWriter writer = Files.newBufferedWriter(Paths.get(csvFile), Charset.forName(charset));
                 CSVPrinter csvPrinter = new CSVPrinter(writer,
                         CSVFormat.DEFAULT.withHeader(fileHeader).withAutoFlush(true))) {
                return csvPrinter;
            } catch (IOException e) {
                e.printStackTrace();
                throw e;
            }
        }
    }

    /**
     * 获得CSVPrinter，用于大数据量写入时
     *
     * @param csvFile
     * @param fileHeader
     * @param charset
     * @return
     * @throws IOException
     */
    public static CSVPrinter csvPrinter(final String csvFile, final String[] fileHeader, final String charset)
            throws IOException {
        return csvPrinter(csvFile, fileHeader, charset, false);
    }

    /**
     * 获得CSVPrinter，用于大数据量写入时
     *
     * @param csvFile
     * @param fileHeader
     * @param append
     * @return
     * @throws IOException
     */
    public static CSVPrinter csvPrinter(final String csvFile, final String[] fileHeader, boolean append)
            throws IOException {
        return csvPrinter(csvFile, fileHeader, "gbk", append);
    }

    /**
     * 获得CSVPrinter，用于大数据量写入时
     *
     * @param csvFile
     * @param fileHeader
     * @return
     * @throws IOException
     */
    public static CSVPrinter csvPrinter(final String csvFile, final String[] fileHeader)
            throws IOException {
        return csvPrinter(csvFile, fileHeader, "gbk");
    }

    /**
     * 读CVS文件
     *
     * @param csvFile    CSV文件
     * @param fileHeader CSV文件头
     * @param skipHeader 是否跳过文件头
     * @param charset    字符集
     * @return
     * @throws IOException
     */
    public static List<CSVRecord> read(final String csvFile, final String[] fileHeader, boolean skipHeader, String charset)
            throws IOException {
        CSVParser csvParser = getCSVParser(csvFile, fileHeader, skipHeader, charset);
        return csvParser.getRecords();
    }

    public static CSVParser getCSVParser(String csvFile, String[] fileHeader, boolean skipHeader, String charset)
            throws IOException {
        CSVFormat format;
        if (skipHeader) {
            format = CSVFormat.DEFAULT.withHeader(fileHeader).withFirstRecordAsHeader().withIgnoreHeaderCase()
                    .withTrim();
        } else {
            format = CSVFormat.DEFAULT.withHeader(fileHeader).withIgnoreHeaderCase().withTrim();
        }
        Reader reader = Files.newBufferedReader(Paths.get(csvFile), Charset.forName(charset));
        return new CSVParser(reader, format);
    }

    /**
     * 读取CSV文件，默认跳过文件头
     *
     * @param csvFile    CSV文件
     * @param fileHeader CSV文件头
     * @param charset    字符集
     * @return CSV记录链表
     * @throws IOException
     */
    public static List<CSVRecord> read(final String csvFile, final String[] fileHeader, String charset)
            throws IOException {
        return read(csvFile, fileHeader, true, charset);
    }

    /**
     * 读取CSV文件，默认跳过文件头
     *
     * @param csvFile    CSV文件
     * @param fileHeader CSV文件头
     * @return CSV记录链表
     * @throws IOException
     */
    public static List<CSVRecord> read(final String csvFile, final String[] fileHeader)
            throws IOException {
        return read(csvFile, fileHeader, true, "gbk");
    }

    /**
     * 读取CSV文件
     *
     * @param csvFile    CSV文件
     * @param fileHeader CSV文件头
     * @param skipHeader 是否跳过文件头
     * @return CSV记录链表
     * @throws IOException
     */
    public static List<CSVRecord> read(final String csvFile, final String[] fileHeader, boolean skipHeader)
            throws IOException {
        return read(csvFile, fileHeader, skipHeader, "gbk");
    }

    /**
     * 获得iterator，用于读大文件
     *
     * @param csvFile    CSV文件
     * @param fileHeader CSV文件头
     * @param skipHeader 是否跳过文件头
     * @param charset    字符集
     * @return
     * @throws IOException
     */
    public static Iterator<CSVRecord> iterator(final String csvFile, final String[] fileHeader, boolean skipHeader, String charset)
            throws IOException {
        CSVParser csvParser = getCSVParser(csvFile, fileHeader, skipHeader, charset);
        return csvParser.iterator();
    }

    /**
     * 获得iterator，用于读大文件，默认跳过文件头
     *
     * @param csvFile    CSV文件
     * @param fileHeader CSV文件头
     * @param charset    字符集
     * @return
     * @throws IOException
     */
    public static Iterator<CSVRecord> iterator(final String csvFile, final String[] fileHeader, String charset)
            throws IOException {
        return iterator(csvFile, fileHeader, true, charset);
    }

    /**
     * 获得iterator，用于读大文件，默认跳过文件头
     *
     * @param csvFile    CSV文件
     * @param fileHeader CSV文件头
     * @return Iterator
     * @throws IOException
     */
    public static Iterator<CSVRecord> iterator(final String csvFile, final String[] fileHeader)
            throws IOException {
        return iterator(csvFile, fileHeader, true, "gbk");
    }

    /**
     * 获得iterator，用于读大文件
     *
     * @param csvFile    CSV文件
     * @param fileHeader CSV文件头
     * @param skipHeader 是否跳过文件头
     * @return Iterator
     * @throws IOException
     */
    public static Iterator<CSVRecord> iterator(final String csvFile, final String[] fileHeader, boolean skipHeader)
            throws IOException {
        return iterator(csvFile, fileHeader, skipHeader, "gbk");
    }
}

